package com.jfs.qy.chain.component;

import com.jfs.qy.chain.AbstractServerStartHandler;
import com.jfs.qy.constant.GlobalConstant;
import com.jfs.qy.enums.NvrApiEnum;
import com.jfs.qy.service.LoginService;
import com.jfs.qy.session.NvrSessionStorage;
import com.jfs.qy.utils.SystemCommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;

/**
 * @Description 责任链中登录链 主要负责nvr登录认证
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022/11/4
 */
@Component(value = LoginComponent.BEAN_NAME)
@Slf4j
public class LoginComponent extends AbstractServerStartHandler implements LoginService {
    public final static String BEAN_NAME = "loginComponent";
    private final SystemCommonUtils systemCommonUtils;
    /**
     * 下一个责任链中的对象
     */
    private final AbstractServerStartHandler abstractServerStartHandler;

    public LoginComponent(SystemCommonUtils systemCommonUtils,
                          @Qualifier(HeartbeatComponent.BEAN_NAME)
                          AbstractServerStartHandler abstractServerStartHandler) {
        this.systemCommonUtils = systemCommonUtils;
        this.abstractServerStartHandler = abstractServerStartHandler;
    }

    /**
     * 登录使用默认配置文件账号和密码
     *
     * @return
     */
    @Override
    public ResponseEntity<String> login() throws URISyntaxException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        return login(systemCommonUtils.getAcount(), systemCommonUtils.getPasswd());
    }

    /**
     * 登录
     *
     * @param acount   登录账号
     * @param password 密码
     * @return
     */
    @Override
    public ResponseEntity<String> login(String acount, String password) throws URISyntaxException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        //拼接请求url
        String requestUrl = systemCommonUtils.getRequestUrl(NvrApiEnum.LOGIN);
        final URI serverUri = new URI(requestUrl);
        //跳过ssl验证
        TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
        SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
        //摘要认证时使用
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(new AuthScope(serverUri.getHost(), serverUri.getPort()),
                new UsernamePasswordCredentials(acount, password));
        final CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(connectionSocketFactory).setDefaultCredentialsProvider(credentialsProvider).build();
        final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setHttpClient(httpclient);
        final RestTemplate restTemplate = new RestTemplate(factory);
        //向NVR  server发送登录认证请求
        return restTemplate.exchange(requestUrl, HttpMethod.POST, null, String.class);
    }


    @Override
    public void handlerOperation() throws URISyntaxException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        //调用登录方法
        ResponseEntity<String> login = login();
        //判断登录是否成功
        if (Objects.nonNull(login) && HttpStatus.OK.equals(login.getStatusCode())) {
            //保存登录回话信息
            final String setCookie = Objects.requireNonNull(login.getHeaders().get(GlobalConstant.SET_COOKIE)).get(0);
            final String xCsrfToken = Objects.requireNonNull(login.getHeaders().get(GlobalConstant.X_CSRF_TOKEN)).get(0);
            //存储认证信息
            NvrSessionStorage.strCookie = setCookie;
            NvrSessionStorage.strXCsrfToken = xCsrfToken;
            //封装统一人证信息请求头
            final HttpHeaders headers = new HttpHeaders();
            headers.set(HttpHeaders.COOKIE, NvrSessionStorage.strCookie);
            headers.set(GlobalConstant.X_CSRF_TOKEN, NvrSessionStorage.strXCsrfToken);
            NvrSessionStorage.headers = headers;
            //调用下一个处理者
            abstractServerStartHandler.handlerOperation();
            if (log.isDebugEnabled()){
                log.debug("登录nvr 设备成功!!!!!!");
            }
        } else {
            log.error("login nvr fail");
        }
    }
}
